package com.lgcns.andteam2.todaymenu;

import java.io.BufferedInputStream;
import java.io.BufferedOutputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.text.DecimalFormat;
import java.text.SimpleDateFormat;
import java.util.Calendar;
import java.util.Date;
import java.util.zip.ZipEntry;
import java.util.zip.ZipInputStream;

import android.content.Context;
import android.content.SharedPreferences;
import android.database.Cursor;
import android.database.sqlite.SQLiteDatabase;
import android.database.sqlite.SQLiteOpenHelper;
import android.preference.PreferenceManager;
import android.text.format.DateFormat;
import android.util.Log;

import com.lgcns.andteam2.todaymenu.db.MenuDBHelper;

public class Util {
    private static final String TAG = Util.class.getSimpleName();
    /** YYYYMMDD */
    public static final SimpleDateFormat dfYyyymmdd = new SimpleDateFormat("yyyyMMdd");
    
    /**
     * 환경설정에 저장된 시간을 java.util.Date로 변환한다.
     * @param prefValue 환경설정에 저장된 시간 문자열(h:mm 형태)
     * @return
     */
    public static Date convertToDate(String prefValue) {
        if(prefValue == null) {
            return null;
        }
        
        String[] time = prefValue.split(":");
        if(time == null || time.length != 2) {
            return null;
        }
        
        Date date = new Date();
        date.setHours(Integer.parseInt(time[0]));
        date.setMinutes(Integer.parseInt(time[1]));
        date.setSeconds(0);
        
        return date;
    }
    
    /**
     * 환경설정에 저장된 시간을 시스템의 시간제에 맞게 포매팅하여 반환한다.
     * @param context
     * @param prefValue 환경설정에 저장된 시간 문자열(h:mm 형태)
     * @return
     */
    public static String formatDatePref(Context context, String prefValue) {
        Date date = convertToDate(prefValue);
        
        if(date == null) {
            return null;
        }
        
        java.text.DateFormat df = DateFormat.getTimeFormat(context);
        return df.format(date);
    }

    /**
     * 문자열을 Integer로 변환한다.
     * 
     * @param value
     * @return
     */
    public static Integer parseInteger(String value) {
        Integer result = null;
        try {
            result = Integer.parseInt(value);
        } catch (Exception e) {
            ;
        }

        return result;
    }

    /**
     * 날짜 문자열(YYYYMMDD)을 날짜(Calendar)로 반환한다.
     * 
     * @param date
     * @return
     */
    public static Calendar parseCalendar(String date) {
        Calendar cal = Calendar.getInstance();
        int year = parseInteger(date.substring(0, 4));
        int month = parseInteger(date.substring(4, 6)) - 1;
        int day = parseInteger(date.substring(6, 8));
        cal.set(year, month, day);

        return cal;
    }

    /**
     * 날짜 문자열을 날짜 포맷으로 반환한다.
     * 
     * @param date 10자리
     * @return
     */
    public static String formatTimeString(String date) {
        Calendar cal = Calendar.getInstance();
        
        int year = parseInteger(date.substring(0, 4));
        int month = parseInteger(date.substring(4, 6)) - 1;
        int day = parseInteger(date.substring(6, 8));
        int hour = parseInteger(date.substring(8, 10));
        cal.set(year, month, day, hour, 0);
        
        SimpleDateFormat df = new SimpleDateFormat("M월  d일 H시");
        
        return df.format(cal.getTime());
    }

    /**
     * SharedPreferences에 환경설정값을 저장한다.
     * 
     * @param context
     * @param key
     * @param value
     */
    public static void savePreference(Context context, String key, String value) {
        SharedPreferences pref = PreferenceManager.getDefaultSharedPreferences(context);
        SharedPreferences.Editor editor = pref.edit();
        editor.putString(key, value);
        editor.commit();
    }

    /**
     * SharedPreferences에 환경설정값을 저장한다.
     * 
     * @param context
     * @param key
     * @param value
     */
    public static void savePreference(Context context, String key, int value) {
        SharedPreferences pref = PreferenceManager.getDefaultSharedPreferences(context);
        SharedPreferences.Editor editor = pref.edit();
        editor.putInt(key, value);
        editor.commit();
    }

    /**
     * SharedPreferences에 환경설정값을 저장한다.
     * 
     * @param context
     * @param key
     * @param value
     */
    public static void savePreference(Context context, String key, boolean value) {
        SharedPreferences pref = PreferenceManager.getDefaultSharedPreferences(context);
        SharedPreferences.Editor editor = pref.edit();
        editor.putBoolean(key, value);
        editor.commit();
    }

    /**
     * SharedPreferences에 저장된 환경설정값을 얻는다.
     * 
     * @param context
     * @param key
     * @param defaultValue
     */
    public static boolean getPreferenceBooleanValue(Context context, String key, boolean defaultValue) {
        SharedPreferences pref = PreferenceManager.getDefaultSharedPreferences(context);
        return pref.getBoolean(key, defaultValue);
    }

    /**
     * SharedPreferences에 저장된 환경설정값을 얻는다.
     * 
     * @param context
     * @param key
     * @param defaultValue
     */
    public static String getPreferenceStringValue(Context context, String key, String defaultValue) {
        SharedPreferences pref = PreferenceManager.getDefaultSharedPreferences(context);
        return pref.getString(key, defaultValue);
    }

    /**
     * SharedPreferences에 저장된 환경설정값을 얻는다.
     * 
     * @param context
     * @param key
     * @param defaultValue
     */
    public static int getPreferenceIntValue(Context context, String key, int defaultValue) {
        SharedPreferences pref = PreferenceManager.getDefaultSharedPreferences(context);
        return pref.getInt(key, defaultValue);
    }

    /**
     * 숫자를 포맷한다.
     * 
     * @param value
     * @param format
     * @return
     */
    public static String formatNumber(int value) {
        DecimalFormat df = new DecimalFormat("#,###");
        return df.format(value);
    }

    /**
     * 숫자를 포맷한다.
     * 
     * @param value
     * @param format
     * @return
     */
    public static String formatNumber(int value, String format) {
        DecimalFormat df = new DecimalFormat(format);
        return df.format(value);
    }

    /**
     * 숫자를 포맷한다.
     * 
     * @param value
     * @param format
     * @return
     */
    public static String formatNumber(double value, String format) {
        DecimalFormat df = new DecimalFormat(format);
        return df.format(value);
    }

    /**
     * 커서를 닫는다.
     * @param c
     */
    public static void close(Cursor c) {
        try {
            if(c != null) {
                c.close();
            }
        } catch(Exception e){}
    }

    /**
     * DB를 닫는다.
     * @param db
     */
    public static void close(SQLiteDatabase db) {
        try {
            if(db != null) {
                db.close();
            }
        } catch(Exception e){}
    }

    /**
     * DB를 닫는다.
     * @param dbHelper
     */
    public static void close(SQLiteOpenHelper dbHelper) {
        try {
            if(dbHelper != null) {
                dbHelper.close();
            }
        } catch(Exception e){}
    }

    /**
     * 서버에서 내려받은 DB(zip) 파일을  압축해제하여 로컬 DB 파일로 복사하는 작업을 수행한다.
     */
    public static void copyDBFile(Context context) throws IOException {
        String packagePath = "/data/data/" + context.getPackageName() + "/";
        File dbFile = new File(packagePath + "databases/" + MenuDBHelper.DB_FILENAME);
        ZipInputStream zis = null;
        FileInputStream fi = null;
        FileOutputStream fo = null;
        
        try {
            // unzip
            context.deleteFile(Constants.TMP_DB_FILE);
            zis = new ZipInputStream(new BufferedInputStream(context.openFileInput(Constants.TMP_DB_ZIP_FILE)));
            ZipEntry ze = null;
            while((ze = zis.getNextEntry()) != null) {
                BufferedOutputStream bo = new BufferedOutputStream(context.openFileOutput(Constants.TMP_DB_FILE, Context.MODE_PRIVATE));
                byte[] buffer = new byte[1024];
                int count;
                while((count = zis.read(buffer)) != -1) {
                    bo.write(buffer, 0, count);
                }
                bo.flush();
                bo.close();
            }
            
            // copy file
            if (dbFile.exists()) {
                dbFile.delete();
            }

            File folder = new File(packagePath + "databases");
            if (!folder.exists()) {
                folder.mkdirs();
            }

            File outfile = new File(packagePath + "databases/" + MenuDBHelper.DB_FILENAME);
            fi = context.openFileInput(Constants.TMP_DB_FILE);
            
            BufferedInputStream in = new BufferedInputStream(fi);
            BufferedOutputStream out = new BufferedOutputStream(new FileOutputStream(outfile));
            
            byte[] buffer = new byte[4096];
            int len = 0;
            while ((len = in.read(buffer)) != -1) {
                out.write(buffer, 0, len);
            }

            out.flush();
        } catch(IOException e) {
            Log.e(TAG, "copyDBFile()", e);
            throw e;
        } finally {
            if(zis != null) try { zis.close(); } catch(Exception e){}
            if(fi != null) try { fi.close(); } catch(Exception e){}
            if(fo != null) try { fo.close(); } catch(Exception e){}
        }
    }
}
